grammar stubcodegrammar;

options {
	language=Java;
}

tokens {
	INDENT;
	DEDENT;
}

@parser::header {
package de.ghost23.stubcodegenerator.recognize;

import de.ghost23.stubcodegenerator.model.*;
import de.ghost23.util.StringHashMap;
}

@lexer::header {
package de.ghost23.stubcodegenerator.recognize;
}

@lexer::members {
	int currentIndentation = 0;
}


prog returns [PackageObj rootPackage, StringHashMap varStatements]
@init {
	$varStatements = new StringHashMap();
}
	:	variabledef[$varStatements]+
		s=structure
	{
		$rootPackage = $s.parsedObject;
	};

variabledef[StringHashMap varStatements]
	:	k=identifier EQUALS STRING
	{
		$varStatements.put($k.text, $STRING.text.substring(1,$STRING.text.length()-1));
	}; 

structure returns [PackageObj parsedObject]
@init {
	parsedObject = new PackageObj();
	parsedObject.name = "root";
}
	:	(	f=file {$parsedObject.childFiles.add($f.parsedObject);}
		|	asp=aspackage {$parsedObject.childPackages.add($asp.parsedObject);}
		)+;

aspackage returns [PackageObj parsedObject]
@init {
	parsedObject = new PackageObj();
}
	:	foldername {$parsedObject.name = $foldername.text.substring(1);}
		(
			INDENT
			(	f=file {$parsedObject.childFiles.add($f.parsedObject);}
			|	asp=aspackage {$parsedObject.childPackages.add($asp.parsedObject);}
			)*
			(DEDENT | EOF)
		)?;

foldername
	:	SLASH identifier;

file	returns [FileObj parsedObject]
	:	(	asclass {$parsedObject = $asclass.parsedObject;}
		|	asinterface {$parsedObject = $asinterface.parsedObject;}
		) asarguments[$parsedObject]?
	;

asclass returns [ClassObj parsedObject]
@init {
	parsedObject = new ClassObj();
}
	:	'c' identifier {$parsedObject.name = $identifier.text;};

asinterface returns [InterfaceObj parsedObject]
@init {
	parsedObject = new InterfaceObj();
}
	:	'i' identifier {$parsedObject.name = $identifier.text;};
	
asarguments [FileObj parsedObject]
	:	individualTemplate{parsedObject.template = $individualTemplate.templateName;};
	
individualTemplate returns [String templateName]
	:	't' STRING {$templateName = $STRING.text.substring(1,$STRING.text.length()-1);};

identifier
	:	identifierStart? identifierPart
	;

identifierStart
	:	DOLLAR
	;

identifierPart
	:	ID
	;

BLANKLINE
	:	NEWLINE TAB* NEWLINE {skip();};

CHANGE_INDENT
@init {
    int tb = 0;
}
	:	(NEWLINE|BLANKLINE) (TAB {tb++;})* {
			if(tb > currentIndentation) {
				emit(new CommonToken(INDENT));
			}else if(tb < currentIndentation) {
				for(int i = 0; i < currentIndentation - tb; i++) {
					emit(new CommonToken(DEDENT));
				}
			}else {
				skip();
			}
			currentIndentation = tb;
		};

ID	:	(	DIGIT
		|	LETTER
		|	UNDERSCORE
		|	DASH
		)+
	;
	
STRING
	:	'"' ('\\'|~('\\'|'\n'|'"'))* '"';

DOLLAR	:	'$';
fragment
UNDERSCORE:	'_';
fragment
DASH	:	'-';
SLASH	:	'/';
QUOTE	:	'"';
EQUALS	:	'=';

fragment
LETTER	:	('a'..'z')|('A'..'Z');
fragment
DIGIT	:	('0'..'9')+;

fragment
TAB		:	'\t';

fragment
NEWLINE	:	'\r'? '\n';

WS	:	' '+ {$channel=HIDDEN;};
